From 6472d247518ec5540e2198c598c791e00bb0b8f0 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 8 Feb 2006 17:27:32 +0100 Subject: [PATCH] Fix Xen timer interface to allow migration of timers among CPUs (using new migrate_timer() call). Fix the locking protocol in light of this addition. Signed-off-by: Keir Fraser --- xen/common/timer.c | 96 ++++++++++++++++++++++++++++++++++++----- xen/include/xen/timer.h | 6 +++ 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/xen/common/timer.c b/xen/common/timer.c index 55f39bfa98..e62a74ee23 100644 --- a/xen/common/timer.c +++ b/xen/common/timer.c @@ -161,46 +161,122 @@ static inline void __stop_timer(struct timer *timer) cpu_raise_softirq(cpu, TIMER_SOFTIRQ); } +static inline void timer_lock(struct timer *timer) +{ + unsigned int cpu; + + for ( ; ; ) + { + cpu = timer->cpu; + spin_lock(&timers[cpu].lock); + if ( likely(timer->cpu == cpu) ) + break; + spin_unlock(&timers[cpu].lock); + } +} + +#define timer_lock_irq(t) \ + do { local_irq_disable(); timer_lock(t); } while ( 0 ) +#define timer_lock_irqsave(t, flags) \ + do { local_irq_save(flags); timer_lock(t); } while ( 0 ) + +static inline void timer_unlock(struct timer *timer) +{ + spin_unlock(&timers[timer->cpu].lock); +} + +#define timer_unlock_irq(t) \ + do { timer_unlock(t); local_irq_enable(); } while ( 0 ) +#define timer_unlock_irqrestore(t, flags) \ + do { timer_unlock(t); local_irq_restore(flags); } while ( 0 ) + void set_timer(struct timer *timer, s_time_t expires) { - int cpu = timer->cpu; unsigned long flags; - spin_lock_irqsave(&timers[cpu].lock, flags); + timer_lock_irqsave(timer, flags); + if ( active_timer(timer) ) __stop_timer(timer); + timer->expires = expires; + if ( likely(!timer->killed) ) __add_timer(timer); - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); } void stop_timer(struct timer *timer) { - int cpu = timer->cpu; unsigned long flags; - spin_lock_irqsave(&timers[cpu].lock, flags); + timer_lock_irqsave(timer, flags); + if ( active_timer(timer) ) __stop_timer(timer); - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); +} + + +void migrate_timer(struct timer *timer, unsigned int new_cpu) +{ + int old_cpu; + unsigned long flags; + + for ( ; ; ) + { + if ( (old_cpu = timer->cpu) == new_cpu ) + return; + + if ( old_cpu < new_cpu ) + { + spin_lock_irqsave(&timers[old_cpu].lock, flags); + spin_lock(&timers[new_cpu].lock); + } + else + { + spin_lock_irqsave(&timers[new_cpu].lock, flags); + spin_lock(&timers[old_cpu].lock); + } + + if ( likely(timer->cpu == old_cpu) ) + break; + + spin_unlock(&timers[old_cpu].lock); + spin_unlock_irqrestore(&timers[new_cpu].lock, flags); + } + + if ( active_timer(timer) ) + __stop_timer(timer); + + timer->cpu = new_cpu; + + if ( likely(!timer->killed) ) + __add_timer(timer); + + spin_unlock(&timers[old_cpu].lock); + spin_unlock_irqrestore(&timers[new_cpu].lock, flags); } void kill_timer(struct timer *timer) { - int cpu = timer->cpu; + int cpu; unsigned long flags; - BUG_ON(timers[cpu].running == timer); + BUG_ON(timers[smp_processor_id()].running == timer); + + timer_lock_irqsave(timer, flags); - spin_lock_irqsave(&timers[cpu].lock, flags); if ( active_timer(timer) ) __stop_timer(timer); timer->killed = 1; - spin_unlock_irqrestore(&timers[cpu].lock, flags); + + timer_unlock_irqrestore(timer, flags); for_each_online_cpu ( cpu ) while ( timers[cpu].running == timer ) diff --git a/xen/include/xen/timer.h b/xen/include/xen/timer.h index f53a7ed35f..ed25521c1a 100644 --- a/xen/include/xen/timer.h +++ b/xen/include/xen/timer.h @@ -65,6 +65,12 @@ extern void set_timer(struct timer *timer, s_time_t expires); */ extern void stop_timer(struct timer *timer); +/* + * Migrate a timer to a different CPU. The timer must have been previously + * initialised by init_timer(). The timer may be active. + */ +extern void migrate_timer(struct timer *timer, unsigned int new_cpu); + /* * Deactivate a timer and prevent it from being re-set (future calls to * set_timer will silently fail). When this function returns it is guaranteed -- 2.30.2